package com.aphrodite.ui.widgets.barcode;

class Modulo10 {

	/**
	 * Calculates a modulo 10 check digit based on the passed numeric data. The
	 * only weight available is odd, this is a common usage. If a non-numeric
	 * value is within the data then NumberFormatException will be thrown. The
	 * first value of data is treated as even.
	 * 
	 * @param data
	 *            The data to encode into a Modulo 10 check digit
	 * @param weightOdd
	 *            Every odd digit will be multiplied by this value
	 * @return the numeric value of the check digit calculated
	 * @see #getMod10CheckDigit(String, int, int)
	 */
	static int getMod10CheckDigit(String data, int weightOdd) throws java.lang.NumberFormatException {
		return getMod10CheckDigit(data, 1, weightOdd, true);
	}

	/**
	 * Calculates a modulo 10 check digit based on the passed numeric data. The
	 * calculated check sum is determined using the weighted values, if there is
	 * a need for no weight to be applied against the odd and/or even characters
	 * then use the value 1. If a non-numeric value is within the data then
	 * NumberFormatException will be thrown. The first value of data is treated
	 * as even.
	 * 
	 * @param data
	 *            The data to encode into a Modulo 10 check digit
	 * @param weightEven
	 *            Every even digit will be multiplied by this value
	 * @param weightOdd
	 *            Every odd digit will be multiplied by this value false if the
	 *            first digit is to be treated as odd
	 * @return the numeric value of the check digit calculated
	 * @see #getMod10CheckDigit(String, int)
	 */
	static int getMod10CheckDigit(String data, int weightEven, int weightOdd) throws java.lang.NumberFormatException {
		return getMod10CheckDigit(data, weightEven, weightOdd, true);
	}

	/**
	 * Calculates a modulo 10 check digit based on the passed numeric data. The
	 * calculated check sum is determined using the weighted values, if there is
	 * a need for no weight to be applied against the odd and/or even characters
	 * then use the value 1. If a non-numeric value is within the data then
	 * NumberFormatException will be thrown.
	 * 
	 * @param data
	 *            The data to encode into a Modulo 10 check digit
	 * @param weightEven
	 *            Every even digit will be multiplied by this value
	 * @param weightOdd
	 *            Every odd digit will be multiplied by this value
	 * @param beginsEven
	 *            true if the first numeric data is to be treated as even, false
	 *            if the first digit is to be treated as odd
	 * @return the numeric value of the check digit calculated
	 * @see #getMod10CheckDigit(String, int, int)
	 * @see #getMod10CheckDigit(String, int)
	 */
	static int getMod10CheckDigit(String data, int weightEven, int weightOdd, boolean beginsEven)
			throws java.lang.NumberFormatException {
		int sum = 0;
		int len = data.length();
		int value;
		int compareValue = beginsEven ? 0 : 1;
		int result = 0;

		for (int i = 0; i < len; i++) {
			value = Integer.parseInt(String.valueOf(data.charAt(i)));
			sum += (i % 2) == compareValue ? weightEven * value : weightOdd * value;
		}

		result = 10 - (sum % 10);

		if (result == 10) {
			result = 0;
		}

		return result;
	}

	/* no public access */
	private Modulo10() {}
}
